import type { DragSource } from '../drag/dragInterface';
import type { DropTarget } from '../drop/dropInterface';
export type SourceType = string;
export type TargetType = string | string[];

export enum HandlerRole {
  SOURCE = 'SOURCE',
  TARGET = 'TARGET',
}

export interface HandlerRegistry {
  //drag
  addSource: (type: SourceType, source: DragSource) => string;
  removeSource: (sourceId: string) => void;
  getSource: (sourceId: string) => DragSource | undefined;
  getSourceType: (sourceId: string) => SourceType | undefined;

  //drop
  addTarget: (accept: TargetType, target: DropTarget) => string;
  removeTarget: (targetId: string) => void;
  getTarget: (targetId: string) => DropTarget | undefined;
  getTargetType: (targetId: string) => TargetType | undefined;
}

export interface DragDropManager {
  //drag
  bindDragEventsForDragNode: (
    sourceId: string,
    dragNode: HTMLElement,
  ) => () => void;
  subscribeStateChange: (listenerFn: () => void) => void;
  isDraggingSource: (handlerId: string) => boolean;
  getRegistry: () => HandlerRegistry;
  getDragStartNodeClientOffset: () => XYCoord | undefined;
  getDragStartEventClientOffset: () => XYCoord | undefined;
  getDragItem: () => any;
  updateDragItem: (newDragItem: any) => void;
  getDragType: () => SourceType;
  //drop
  bindEventsForDropNode: (
    targetId: string,
    dropNode: HTMLElement,
  ) => () => void;
  getDropResult: () => any;
  getDropEventClientOffset: () => XYCoord | undefined;
  getDropNodeClientOffset: () => XYCoord | undefined;
  removeEventListeners: () => void;
  canDropOnTarget: (targetId: string) => boolean;
  isOverTarget: (targetId: string) => boolean;
}

export interface XYCoord {
  x: number;
  y: number;
}
